﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Reflection;

namespace Deeper.DataAccess
{
	/// <summary>
	/// 数据列
	/// </summary>
	[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
	public class HColumnAttribute : Attribute
	{
		/// <summary>
		/// 列id
		/// </summary>
		public string ColumnId { set; get; }
		public HColumnAttribute(string ColumnName)
		{
			this.ColumnName = ColumnName;
			this.Remake = ColumnName;
			this.Commont = ColumnName;
			this.DataType = "int";
			this.Length = 0;
			this.DefaultValue = string.Empty;
			this.IsPrimary = false;
			this.IsIdentity = false;
			this.IsNullable = true;
			this.Field = null;
		}
		public PropertyInfo Field { set; get; }
		/// <summary>
		/// 是否主键
		/// </summary>
		public bool IsPrimary { get; set; }
		/// <summary>
		/// 是否自增型
		/// </summary>
		public bool IsIdentity { set; get; }
		/// <summary>
		/// 可为空
		/// </summary>
		public bool IsNullable { set; get; }
		/// <summary>
		/// 列名
		/// </summary>
		public string ColumnName { get; protected set; }
		/// <summary>
		/// 数据类型
		/// </summary>
		public string DataType { set; get; }
		/// <summary>
		/// 是否唯一
		/// </summary>
		public bool IsUniqueness { set; get; }
		/// <summary>
		/// sql脚本的数据类型（包括长度）
		/// </summary>
		public string SqlDataType { set; get; }

		/// <summary>
		/// 长度
		/// </summary>
		public int Length { get; set; }
		/// <summary>
		/// 默认值
		/// </summary>
		public string DefaultValue { set; get; }
		/// <summary>
		/// 中文说明
		/// </summary>
		public string Remake { set; get; }
		/// <summary>
		/// 备注
		/// </summary>
		public string Commont { set; get; }

		public string ToString()
		{
			string str = string.Format("[HColumn(\"{0}\", Remake = \"{1}\", DataType = \"{2}\"", this.ColumnName, this.Remake, this.DataType);
			if (IsPrimary) str += " , IsPrimary = true";
			if (IsIdentity) str += " , IsIdentity = true";
			if (Length > 0) str += " , Length =" + this.Length;
			if (IsUniqueness) str += " , IsUniqueness = true";
			if (IsNullable) str += " , IsNullable = true";
			str += ")]";
			return str;
			//[HColumn("@CName@", Remake = "@CRemake@", DataType = "@DbType@", IsPrimary = @IsPK@, IsIdentity = @IsId@ , Length = @CLen@ , IsNullable = @IsNull@,IsUniqueness = @IsUniqueness@ )]
		}

		#region 判断字符串类型
		/// <summary>
		/// 返回数据库字段类型
		/// </summary>
		public DbType ColumnDbType
		{
			get
			{
				DbType type = System.Data.DbType.AnsiString;
				if (this.DataType != null)
				{
					switch (this.DataType.ToLower())
					{
						case "ansistring":
							type = DbType.AnsiString;
							break;

						case "ansistringfixedlength":
							type = DbType.AnsiStringFixedLength;
							break;
						case "binary":
							type = DbType.Binary;
							break;
						case "byte":
							type = DbType.Byte;
							break;
						case "autoincrement":
							type = DbType.Int32;
							break;
						case "bigint":
							type = DbType.Int64;
							break;
						case "char":
							type = DbType.AnsiStringFixedLength;
							break;
						case "text":
							type = DbType.AnsiString;
							this.Length = -1;
							break;
						case "nchar":
							type = DbType.StringFixedLength;
							break;
						case "nvarchar":
							type = DbType.String;
							break;
						case "varchar":
							type = DbType.AnsiString;
							break;
						case "int":
							type = DbType.Int32;
							break;
						case "smallint":
							type = DbType.Int16;
							break;
						case "tinyint":
							type = DbType.Int16;
							break;
						case "integer":
							type = DbType.Int32;
							break;
						case "bit":
							type = DbType.Boolean;
							break;
						case "date":
							type = DbType.Date;
							break;
						case "datetime":
							type = DbType.DateTime;
							break;
						case "image":
							type = DbType.Binary;
							break;
						case "blob":
							type = DbType.Binary;
							break;
						case "clob":
							type = DbType.Binary;
							break;
						case "numberic":
							type = DbType.Int32;
							break;
						case "decimal":
							type = DbType.Decimal;
							break;
						case "double":
							type = DbType.Double;
							break;
						case "guid":
							type = DbType.Guid;
							break;
						case "currency":
							type = DbType.Currency;
							break;
					}
				}
				return type;

			}
		}

		/// <summary>
		/// 判断字段是否是字符串字段
		/// </summary>
		public bool IsString
		{
			get
			{
				return TypeContainStrings(new string[] { "char", "text", "nvarchar", "varchar", "nvarchar2,nchar" });
			}
		}

		/// <summary>
		/// 判断字段是否是整数字段
		/// </summary>
		public bool IsInteger
		{
			get
			{
				return TypeContainStrings(new string[] { "int", "bigint", "smallint", "numeric", "tinyint", "integer", "autoincrement" });
			}
		}

		/// <summary>
		/// 判断字段是否是布尔类型
		/// </summary>
		public bool IsBoolean
		{
			get
			{
				return TypeContainStrings(new string[] { "bit" });
			}
		}

		/// <summary>
		/// 字段是否是数值的字段
		/// </summary>
		public bool IsNumberic
		{
			get
			{
				return TypeContainStrings(new string[] { "number", "float", "real", "double", "money", "smallmoney" });
			}
		}
		public bool IsDecimal
		{
			get
			{
				return TypeContainStrings(new string[] { "decimal" });
			}
		}

		/// <summary>
		/// 是否是日期类型的字段
		/// </summary>
		public bool IsDateTime
		{
			get
			{
				return TypeContainStrings(new string[] { "date", "datetime" });
			}
		}

		/// <summary>
		/// 是否是二进制类型的字段
		/// </summary>
		public bool IsBinary
		{
			get
			{
				return TypeContainStrings(new string[] { "binary", "long", "image", "blob", "clob" });
			}
		}

		/// <summary>
		/// 判断类型
		/// </summary>
		/// <param name="items"></param>
		/// <returns></returns>
		protected bool TypeContainStrings(string[] items)
		{
			string type = this.DataType;
			if (type != null)
			{
				type = type.ToLower();
				foreach (string item in items)
				{
					if (type.IndexOf(item) >= 0)
						return true;
				}
			}
			return false;
		}


		/// <summary>
		/// 字段对应的数据类型
		/// </summary>
		public Type ValueType
		{
			get
			{
				if (this.IsDecimal)
					return typeof(decimal);
				if (this.IsBoolean)
					return typeof(bool);
				if (this.IsInteger)
					return typeof(int);
				if (this.IsBinary)
					return typeof(byte[]);
				if (this.IsDateTime)
					return typeof(DateTime);
				if (this.IsNumberic)
					return typeof(double);
				return typeof(string);
			}
		}



		/// <summary>
		/// 字段对应的数据类型名称
		/// </summary>
		public string ValueTypeName
		{
			get
			{
				if (this.IsDecimal)
				{
					if (this.IsNullable)
						return "decimal?";
					else
						return "decimal";
				}
				if (this.IsBoolean)
				{
					if (this.IsNullable)
						return "bool?";
					else
						return "bool";
				}
				if (this.IsInteger)
				{
					if (this.IsNullable)
						return "int?";
					else
						return "int";
				}
				if (this.IsBinary)
					return "byte[]";
				if (this.IsDateTime)
				{
					if (this.IsNullable)
						return "DateTime?";
					else
						return "DateTime";
				}
				if (this.IsNumberic)
				{
					if (this.IsNullable)
						return "double?";
					else
						return "double";
				}
				return "string";

			}
		}

		public string ValueTypeNameWithNoNullAble
		{
			get
			{
				if (this.IsDecimal) return "decimal";
				if (this.IsBoolean) return "bool";
				if (this.IsInteger) return "int";
				if (this.IsBinary) return "byte[]";
				if (this.IsDateTime) return "DateTime";
				if (this.IsNumberic) return "double";
				return "string";

			}
		}

		public Type ValueTypeWithNoNullAble
		{
			get
			{
				if (this.IsDecimal) return typeof(decimal);
				if (this.IsBoolean) return typeof(bool);
				if (this.IsInteger) return typeof(int);
				if (this.IsBinary) return typeof(byte[]);
				if (this.IsDateTime) return typeof(DateTime);
				if (this.IsNumberic) return typeof(double);
				return typeof(string);

			}
		}
		#endregion


	}
}
